/*
 SGSortingGameViewController.m
 Date Created: Feburary 24, 2010
 
 Authors: Karanvir Gill <viper1029@gmail.com>
	        Frank Lau <flaua@sfu.ca>
          Karol Krizka <kkrizka@gmail.com>
 
 Copyright (C) 2010 Green-Power
 
 URL: http://code.google.com/p/green-power
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 3 of the License, or
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
 $Id$
 
 */

#import "SGSortingGameViewController.h"
#import "SGPauseViewController.h"
#import "SGTutorialModeViewController.h"
#import "SGRecyclableType.h"
#import "SGBinType.h"
#import "SGBin.h"
#import "SGSummaryViewController.h"
#import "SGEndGameViewController.h"
#import "SGRecyclableItem.h"


@implementation SGSortingGameViewController
@synthesize levelScoreLabel;
@synthesize totalScoreLabel;
@synthesize sortingGameLevel;
@synthesize livesLeftLabel;
@synthesize levelLabel;
@synthesize itemsLeftLabel;

- (SGSortingGameViewController*)initWithSortingGame:(SGSortingGame *)newSortingGame {
	self = [super init];
	if( self ) {
		// Initialize instance variables    
    sortingGame=[newSortingGame retain];
    
    if(sortingGame.lastLevel==nil) {
      sortingGame.nextLevel; // Initialize with level 1
    }

    sortingGameLevel=[sortingGame.lastLevel retain]; // Makes access easier

		// Listen for inactive notifications to pause the game on calls and screen
		// locking.
		[[NSNotificationCenter defaultCenter] addObserver:self 
																						 selector:@selector(handleNotification:)
																								 name:UIApplicationWillResignActiveNotification 
																							 object:[UIApplication sharedApplication]];	
	}
	return self;
}

- (void)viewDidLoad {
  [super viewDidLoad];	

  // Draw bins
  binsOnScreen = [[NSMutableArray alloc] init]; // Will contain all the bins after drawBins is called
  [self drawBins];
  
  // Will keep track of which items are on screen
	itemsOnScreen = [[NSMutableArray alloc] init];

  // Initialize the tutorial mode, all items start of as unexplained
  unexplainedItemTypes=[[SGRecyclableType listOfficialTypes] mutableCopy];
  [unexplainedItemTypes retain];
  
  // Initialize all of the fields with proper values
  [self reloadView];
  
  // Prepare the sound effects
  wrongBinSound = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath: [[NSBundle mainBundle] pathForResource:@"uh_oh" ofType:@"aiff"]] error:nil];
  correctBinSound = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath: [[NSBundle mainBundle] pathForResource:@"can" ofType:@"wav"]] error:nil];
	correctBinSound.volume = 0.35;
  // Buffer the sounds, so there is little lag later on
  [wrongBinSound prepareToPlay];
  [correctBinSound prepareToPlay];
  
  // Recreate any existing items
  for(SGRecyclableItem *item in sortingGame.items) {
    // Create the item and add it to the subview
    SGRecyclableItemView *itemView = [[SGRecyclableItemView alloc] initWithItem:item];
    [itemView setUserInteractionEnabled:YES];
    [self.view addSubview:itemView];
    [itemsOnScreen addObject:itemView];
    [itemView release];
  }
}


- (void)stopTimers {
  [createTimer invalidate];
  [moveTimer invalidate];
  [createTimer release];
  [moveTimer release]; 
}

- (void)startTimers {
  // All items shold be spaced 100 pixels appart. So the time between items is
  // distance = velocity * time
  // time = distance / velocity
  //
  // SGSortingGameLevel#speedOfItems returns speed as # pixels / 0.02 s
  float timeBetweenNewItems=100.0*0.02/sortingGameLevel.speedOfItems;
  NSLog(@"Time %f Speed %d",timeBetweenNewItems,sortingGameLevel.speedOfItems);
  createTimer=[[NSTimer scheduledTimerWithTimeInterval:timeBetweenNewItems 
                                                target:self 
                                              selector:@selector(createItem) 
                                              userInfo:nil 
                                               repeats:YES] retain];
	moveTimer=[[NSTimer scheduledTimerWithTimeInterval:0.02 target:self 
                                            selector:@selector(moveItems) 
                                            userInfo:nil 
                                             repeats:YES] retain];
}

//Controlled by a timer to create new objects at set time intervals 
- (void)createItem {
	if(sortingGameLevel.numItemsDisplayed < sortingGameLevel.totalNumItems) {
		
		// Determine if the item will be a life giver
		BOOL isLifeGiver=NO;
		NSInteger probabilityOfLifeGiver = (5-sortingGameLevel.livesLeft);
		// If the random number is less than or equal to the probability the items is life giver
		if(probabilityOfLifeGiver !=0 && probabilityOfLifeGiver >= arc4random() % 101){
			isLifeGiver=YES;
		}
		
		SGRecyclableItem *createdItem = [sortingGameLevel popNextItem];
    createdItem.x=160;
    createdItem.y=-50;
    createdItem.lifeGiver=isLifeGiver;
		
		// Create the item and add it to the subview
		SGRecyclableItemView *createdItemView = [[SGRecyclableItemView alloc] initWithItem:createdItem];
		[createdItemView setUserInteractionEnabled:YES];
		[self.view addSubview:createdItemView];
		[itemsOnScreen addObject:createdItemView];
		[createdItemView release];
    
    // Handle tutorial mode
    if(sortingGame.tutorialModeOn && [unexplainedItemTypes containsObject:createdItem.type]) {
      // This is an unexplained item!
      NSLog(@"Unexplained item %@",createdItem.type.uniqueName);
      [unexplainedItemTypes removeObject:createdItem.type];
      
      SGTutorialModeViewController *tutorialModeViewController=[[SGTutorialModeViewController alloc] initWithType:createdItem.type];
      [self setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
      [self presentModalViewController:tutorialModeViewController animated:YES];
      [tutorialModeViewController.tutorialModeSwitch addTarget:self
                                                        action:@selector(tutorialModeOnOff:)
                                              forControlEvents:UIControlEventValueChanged];
      
      [tutorialModeViewController release];
    }
    
    itemsLeftLabel.text=[NSString stringWithFormat:@"%d",(sortingGameLevel.totalNumItems-sortingGameLevel.numItemsDisplayed)];
  }
}

// Loop through all of the items and move them
- (void)moveItems {
  // Check if any of the bins have to be highlighted/dehighlighted
  NSMutableArray *binsShouldBeHighlighted=[NSMutableArray arrayWithCapacity:itemsOnScreen.count];
  for(SGRecyclableItemView *tempItem in itemsOnScreen) {
    SGBin *dropInBin=[self binItemIsOn:tempItem];
    if(dropInBin) [binsShouldBeHighlighted addObject:dropInBin];
  }
  for(SGBin *tempBin in binsOnScreen) {
    BOOL shouldBeHighlighted=[binsShouldBeHighlighted containsObject:tempBin];
    tempBin.isHighlighted=shouldBeHighlighted;
  }
  
	// Moves all the items
	for(int i=0;i<itemsOnScreen.count;i++){
		SGRecyclableItemView *tempItem = [itemsOnScreen objectAtIndex:i];
		
		if(!tempItem.isBeingDragged) {
			tempItem.center = CGPointMake(tempItem.center.x,tempItem.center.y+sortingGameLevel.speedOfItems);
      // Reached the end of the conveyor belt, throw into garbage
			if(tempItem.center.y > 410) {
				if(tempItem.item.type.uniqueName != @"garbage"){// Check if recyclable item has been dropped into garbage
          [sortingGameLevel itemDropped:NO];
					[wrongBinSound play];
          [self animateCheckmark:@"bad.png" fromLocation:tempItem.center];
          NSLog(@"BAD! %f %@",tempItem.center.y,tempItem.item.type.uniqueName);
				} else {
          if(tempItem.item.lifeGiver) {// Add a life if the item is a life giver
            sortingGameLevel.livesLeft++;
          }
          [sortingGameLevel itemDropped:YES];
          [self animateCheckmark:@"good.png" fromLocation:tempItem.center];
					[correctBinSound play];
				}

        [tempItem removeFromSuperviewWithAnimation:SGRecyclableItemViewRemoveFromSuperviewAnimationStyleDropDown];
				[itemsOnScreen removeObjectAtIndex:i];
        i--; // Go over again
			}
		}
	}
	
  // Loop through all of the items and see if they have been moved by the user
  // If they have been moved, remove them and add to score if necessary
	// Checks if the item is dropped in the correct bin
	for(int i=0;i<itemsOnScreen.count;i++){
    SGRecyclableItemView *tempItem = [itemsOnScreen objectAtIndex:i];
    if(!tempItem.isBeingDragged && tempItem.hasBeenDropped) {
      SGRecyclableItemViewRemoveFromSuperviewAnimationStyle removeAnimationStyle=SGRecyclableItemViewRemoveFromSuperviewAnimationStyleDissapear;
      
      SGBin *tempBin = [self binItemIsOn:tempItem];
      if([tempBin itemAccepted:tempItem]) {//check if items is in correct bin
        // Update scores
        if(tempItem.item.lifeGiver){// Add a life if the item is a life giver
          sortingGameLevel.livesLeft++;
        }
        [sortingGameLevel itemDropped:YES];
        [sortingGameLevel incrementScore:tempItem.item.type.depositValue];
        [self animateCheckmark:@"good.png" fromLocation:tempItem.center];
        [correctBinSound play];
        removeAnimationStyle=SGRecyclableItemViewRemoveFromSuperviewAnimationStyleDropDown;
      }	else if (tempBin!=nil) { // Item dropped in wrong bin
        [sortingGameLevel itemDropped:NO];
        [self animateCheckmark:@"bad.png" fromLocation:tempItem.center];
        [wrongBinSound play];
        removeAnimationStyle=SGRecyclableItemViewRemoveFromSuperviewAnimationStyleDropDown;
      } else {
        // Dropped outside of a bin!
        [sortingGameLevel itemDropped:NO];
        removeAnimationStyle=SGRecyclableItemViewRemoveFromSuperviewAnimationStyleDissapear;
      }
      
      // All user-moved items should be removed
      [tempItem removeFromSuperviewWithAnimation:removeAnimationStyle];
      [itemsOnScreen removeObjectAtIndex:i];
      i--; // We just removed the current index, so go over it again..
    }
  }	

  // Update the UI
  levelScoreLabel.text = [NSString stringWithFormat:@"%i", sortingGameLevel.score];
  totalScoreLabel.text = [NSString stringWithFormat:@"%i", sortingGame.score];
	livesLeftLabel.text = [NSString stringWithFormat:@"%i", sortingGameLevel.livesLeft];
  itemsLeftLabel.text = [NSString stringWithFormat:@"%i", sortingGameLevel.totalNumItems-sortingGameLevel.numItemsDisplayed];

  // Check the game state
	if(sortingGameLevel.livesLeft <= 0) {
		NSLog(@"Game Over");
		[self showEndGame];
	}
	
  
  
	if(sortingGameLevel.numItemsDisplayed == sortingGameLevel.totalNumItems && itemsOnScreen.count == 0) {
		NSLog(@"End of level");
    [self showLevelSummary];	
  }
}

-(void)drawBins{
	
	NSArray *arrayWithAllBinTypes = [[NSArray alloc] initWithArray:[SGBinType listBinTypes]];
	
	// Setup the bins on the left
	int yLoc = 0;
	for(int i=0;i<4;i++) {
    SGBinType *binType=[arrayWithAllBinTypes objectAtIndex:i];
		SGBin *tempBin = [[SGBin alloc] initWithType:binType xLocation:2 yLocation:(50+yLoc)];
		[self.view addSubview:tempBin];
		[binsOnScreen addObject:tempBin];
		[tempBin release];
		yLoc = yLoc + 90;
	}
	
	// Setup the bins on the right
	yLoc = 0;
	for(int i=4;i<7;i++){
		SGBin *tempBin = [[SGBin alloc] initWithType:[arrayWithAllBinTypes objectAtIndex:i] xLocation:233 yLocation:(100+yLoc)];
		[self.view addSubview:tempBin];
		[binsOnScreen addObject:tempBin];
		[tempBin release];
		yLoc = yLoc + 90;
	}
}


- (void) reloadView {  
  // Reset the labels
  levelScoreLabel.text = [NSString stringWithFormat:@"%i", sortingGameLevel.score];
  totalScoreLabel.text = [NSString stringWithFormat:@"%i", sortingGame.score];
	livesLeftLabel.text = [NSString stringWithFormat:@"%i", sortingGameLevel.livesLeft];
  itemsLeftLabel.text = [NSString stringWithFormat:@"%i", sortingGameLevel.totalNumItems-sortingGameLevel.numItemsDisplayed];
  levelLabel.text = [NSString stringWithFormat:@"%i", sortingGameLevel.level];

  NSLog(@"reload view");
}

- (void)viewWillAppear:(BOOL)animated {
  // Make sure to update labels before displaying view
  [self reloadView];
}

- (void)viewDidAppear:(BOOL)animated {
  NSLog(@"SGSortingGameViewController@viewDidAppear:%d",animated);
  [self startTimers];
}

- (void)viewWillDisappear:(BOOL)animated {
  // View dissapeared, so stop the game
  [self stopTimers];
}

- (IBAction)showPauseMenu:(id)sender {	
	SGPauseViewController *pauseViewController=[[SGPauseViewController alloc] init];
  [pauseViewController loadView];
  [pauseViewController.tutorialModeSwitch setOn:sortingGame.tutorialModeOn animated:NO];
  [pauseViewController.tutorialModeSwitch addTarget:self
                                             action:@selector(tutorialModeOnOff:)
                                   forControlEvents:UIControlEventValueChanged];

  [[self navigationController] pushViewController:pauseViewController animated:NO];
  
  [pauseViewController release];
}

- (IBAction)tutorialModeOnOff:(id)sender {
  if([sender isKindOfClass:[UISwitch class]]) {
    UISwitch *senderSwitch=(UISwitch *)sender;
    BOOL on=senderSwitch.on;
    sortingGame.tutorialModeOn=on;
    [sortingGame.managedObjectContext save:nil];
  }
}

- (void)didReceiveMemoryWarning {
	// Releases the view if it doesn't have a superview.
	[super didReceiveMemoryWarning];
	
	// Release any cached data, images, etc that aren't in use.
}

- (void)showLevelSummary {
  [sortingGame.managedObjectContext save:nil];
  
	SGSummaryViewController *summaryViewController=[[SGSummaryViewController alloc] 
																									initWithLevel:sortingGame.lastLevel]; 
	
	[[self navigationController] pushViewController:summaryViewController animated:YES];
  NSLog(@"Summary View Controller has been pushed");
	[summaryViewController release];
  [sortingGameLevel release];

  sortingGameLevel=[sortingGame.nextLevel retain];
}

- (void)showEndGame {
  [sortingGame.owner recordScore:sortingGame.score achievedOn:[NSDate date]];
  [sortingGame.managedObjectContext save:nil];

	SGEndGameViewController *endGameViewController=[[SGEndGameViewController alloc] initWithGame:sortingGame];
	[[self navigationController] pushViewController:endGameViewController animated:YES];
  NSLog(@"End Game View Controller has been pushed");
	[endGameViewController release];
}


- (void)viewDidUnload {
	// Release any retained subviews of the main view.
	// e.g. self.myOutlet = nil;
}

- (SGBin *)binItemIsOn:(SGRecyclableItemView *)item {
  CGRect itemRect = [item frame];
  CGFloat itemArea = itemRect.size.height*itemRect.size.width;
  
  CGFloat bestIntersectionArea=0;
  SGBin *bestBinCandidate=nil;
  
  for(SGBin *bin in binsOnScreen) {
    CGRect binRect = [bin frame];

    // Find out how much the item and bin overlap
    CGRect intersectionRect = CGRectIntersection(itemRect, binRect);
    CGFloat intersectionArea = intersectionRect.size.height*intersectionRect.size.width;

    // If the item is more then 35 percent in the bin, then count it as
    // dropped in the bin, otherwise its dropped outside the bin
    // Also the intersection area must be bigger than intersection area with a
    // previous bin
    if(intersectionArea>itemArea*0.35 && intersectionArea > bestIntersectionArea) {
      bestIntersectionArea=intersectionArea;
      bestBinCandidate=bin;
    }
  }
  return bestBinCandidate;
}

- (void)animateCheckmark:(NSString *)imageName fromLocation:(CGPoint)pos {
  UIImage *checkImage=[UIImage imageNamed:imageName];
  UIImageView *checkImageView=[[UIImageView alloc] initWithImage:checkImage];
  checkImageView.center=pos;
  
  [UIView beginAnimations:@"checkmark" context:checkImageView];
  [UIView setAnimationDuration:1];
  [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
  [UIView setAnimationDelegate:self];
  [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
  pos.y-=50;
  checkImageView.alpha=0;
  checkImageView.center=pos;
  [UIView commitAnimations];
  
  [self.view addSubview:checkImageView];
  
  [checkImageView release];
}

// Make sure to remove checkmarks from the view after their animation finished
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
  if([animationID isEqualToString:@"checkmark"]) {
    UIView *checkImageView=(UIView *)context;
    [checkImageView removeFromSuperview];
  }
}

- (void)handleNotification:(NSNotification *)notification {
	if(moveTimer!=nil && createTimer!=nil) // Do not pause if game is already paused
  {
		[self showPauseMenu:nil];
  }
}

- (void)dealloc {
  [sortingGame release];
  [sortingGameLevel release];
  [unexplainedItemTypes release];
  [correctBinSound release];
  [wrongBinSound release];
  
  [super dealloc];
}

@end
